# File: src/llm_interface/prompt_builder.py
# (REVISED TO FIX PATH CALCULATION)

import logging
from typing import Dict, Any, List, Optional
from pathlib import Path

# Use core logger setup (assuming it's configured before planner calls this)
from ..core.logging_setup import get_logger
from ..core.exceptions import AgentError # Import AgentError for wrapping

logger = get_logger(__name__)

# --- Determine Project Root and Prompts Directory ---
# 假设这个文件位于 src/llm_interface/prompt_builder.py
try:
    # 从当前文件位置向上回溯找到项目根目录 (project_root)
    # __file__ -> prompt_builder.py
    # .parent -> llm_interface/
    # .parent -> src/
    # .parent -> project_root/
    _project_root = Path(__file__).resolve().parent.parent.parent
    _prompts_dir = _project_root / "config" / "prompts"
    if not _prompts_dir.is_dir():
         # 如果计算出的路径不对，尝试使用当前工作目录作为后备
         logger.warning(f"Calculated prompts directory does not exist or is not a directory: {_prompts_dir}")
         _prompts_dir = Path.cwd() / "config" / "prompts"
         logger.warning(f"Falling back to CWD relative prompts directory: {_prompts_dir}")
except NameError:
     # 如果 __file__ 未定义 (例如在交互式环境中)
     _prompts_dir = Path.cwd() / "config" / "prompts"
     logger.warning(f"Could not determine project root reliably using __file__, using CWD relative prompts directory: {_prompts_dir}")

# 在模块加载时打印一次最终使用的 prompts 目录路径
logger.info(f"PromptBuilder initialized. Using prompts directory: {_prompts_dir}")
# ----------------------------------------------------


def load_prompt_template(template_name: str) -> str:
    """Loads a prompt template from the determined prompts directory."""
    try:
        # 使用预先计算好的 _prompts_dir 来构建路径
        # 支持 template_name 包含子目录, e.g., "planning/decide_next_action"
        prompt_path = _prompts_dir / template_name
        # 如果没提供 .txt 后缀，则自动添加
        if not template_name.endswith(".txt"):
            prompt_path = prompt_path.with_suffix(".txt")

        logger.debug(f"Attempting to load prompt template from: {prompt_path}")

        # 使用 is_file() 检查路径是否是一个存在的文件
        if not prompt_path.is_file():
            logger.error(f"Prompt template not found or is not a file at: {prompt_path}")
            logger.error(f"Checked directory: {_prompts_dir}. Template name given: {template_name}")
            raise FileNotFoundError(f"Prompt template '{template_name}' not found at '{prompt_path}'.")

        with open(prompt_path, "r", encoding="utf-8") as f:
            template = f.read()
        logger.debug(f"Loaded prompt template '{template_name}' successfully.")
        return template

    except FileNotFoundError as e: # 首先捕获 FileNotFoundError
         # 不需要完整的 traceback，错误信息已经足够
         logger.error(f"Error loading prompt template '{template_name}': {e}", exc_info=False)
         raise # 重新抛出 FileNotFoundError
    except Exception as e:
        # 捕获其他意外错误
        logger.error(f"Unexpected error loading prompt template '{template_name}': {e}", exc_info=True)
        # 包装成 IOError 或直接重新抛出
        raise IOError(f"Failed to load prompt template '{template_name}' due to unexpected error.") from e


def format_prompt(template_name: str, context: Dict[str, Any]) -> str:
    """Loads a template and formats it with the provided context."""
    try:
        template = load_prompt_template(template_name)
        # 使用 .format() 进行简单的占位符替换
        formatted_prompt = template.format(**context)
        return formatted_prompt
    except KeyError as e:
        # 处理 context 字典中缺少键的情况
        logger.error(f"Missing key '{e}' in context for prompt template '{template_name}'. Context keys: {list(context.keys())}")
        # 抛出 ValueError 以指示数据问题
        raise ValueError(f"Missing context key '{e}' needed for prompt template '{template_name}'.") from e
    except FileNotFoundError as e: # 捕获来自 load_prompt_template 的错误
         # 在 load_prompt_template 中已经记录过日志
         # 可以选择重新包装成 AgentError 给 Orchestrator 处理，或者直接让 FileNotFoundError 传播出去
         # 这里我们包装一下，保持一致性
         logger.error(f"Failed to format prompt because template file '{template_name}' was not found.")
         raise AgentError(f"Prompt file '{template_name}' not found.") from None # from None 避免重复的 traceback
    except Exception as e:
        # 处理其他格式化或加载过程中的意外错误
        logger.error(f"Error formatting prompt '{template_name}': {e}", exc_info=True)
        # 包装成 ValueError
        raise ValueError(f"Failed to format prompt '{template_name}'.") from e